package xuecheng.spring.boot.start.common.encryption;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import xuecheng.spring.boot.start.common.MyStringUtils;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;

/**
 * desc des 实现
 * <p/>
 *
 * @author PengXueCheng
 * @mail yingcheng1016@gmail.com,chengpx_org@163.com
 * create time 2020/3/9 17:27
 * project spring-boot-start-common
 * <p/>
 **/
@Slf4j
public class DESUtils {

    /**
     * 加密私钥，长度不能够小于8位字节
     */
    private String keyscert;

    /**
     * @param keyscert 加密私钥，长度不能够小于8位字节
     */
    public DESUtils(String keyscert) {
        this.keyscert = keyscert;
    }

    /**
     * 加密
     *
     * @param data 待加密数据
     * @return
     */
    public String encode(String data) {
        if (StringUtils.isEmpty(data)) {
            return null;
        }
        Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
        byte[] bytes = doFinal(cipher, data.getBytes());
        return MyStringUtils.byte2hex(bytes);

    }

    /**
     * 解密
     *
     * @param data 带解密数据
     * @return
     */
    public String decode(String data) {
        if (StringUtils.isEmpty(data)) {
            return null;
        }
        try {
            Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
            return new String(doFinal(cipher, MyStringUtils.hex2byte(data.getBytes())));
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    private byte[] doFinal(Cipher cipher, byte[] bytes) {
        if (null == cipher) {
            return new byte[0];
        }
        try {
            return cipher.doFinal(bytes);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
            log.error(cipher + "_" + bytes + "_" + e.getMessage(), e);
            return new byte[0];
        }
    }

    private Cipher getCipher(int encryptMode) {
        String algorithmDes = "DES/CBC/PKCS5Padding";
        Key secretKey;
        Cipher cipher;
        try {
            DESKeySpec dks = new DESKeySpec(keyscert.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            secretKey = keyFactory.generateSecret(dks);
            cipher = Cipher.getInstance(algorithmDes);
        } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException e) {
            log.error(keyscert + "_" + algorithmDes + "_" + e.getMessage(), e);
            return null;
        }
        AlgorithmParameterSpec paramSpec = new IvParameterSpec("12345678".getBytes());
        try {
            cipher.init(encryptMode, secretKey, paramSpec);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            log.error(encryptMode + "_" + secretKey + "_" + paramSpec + "_" + e.getMessage(), e);
            return null;
        }
        return cipher;
    }
}
